/*
 * Copyright (c) 2018. 玺得（深圳）科技有限公司.保留所有权利. http://www.pi-top.com/ 玺得（深圳）科技有限公司保留所有代码著作权.如有任何疑问请访问官方网站与我们联系. 代码只针对特定需求定制编码，不得在未经允许或授权的情况下对外传播扩散.恶意传播者，法律后果自行承担. 本代码仅用于pps-cloud系统.
 */
package com.pitop.material.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baidu.fsg.uid.UidGenerator;
import com.pitop.bom.entity.BomDetailType;
import com.pitop.core.base.BaseDAO;
import com.pitop.core.base.BaseSVImpl;
import com.pitop.core.entity.BeanRet;
import com.pitop.core.entity.Page;
import com.pitop.core.exceptions.BaseException;
import com.pitop.core.exceptions.MaterialException;
import com.pitop.core.tools.FileUtil;
import com.pitop.core.tools.StringTools;
import com.pitop.core.tools.excel.ExcelUtils;
import com.pitop.material.VO.MaterialExcel;
import com.pitop.material.VO.MaterialVO;
import com.pitop.material.dao.MaterialDAO;
import com.pitop.material.dao.MaterialLogDAO;
import com.pitop.material.dao.MaterialSupplierDAO;
import com.pitop.material.entity.*;
import com.pitop.supplier.dao.SupplierDAO;
import com.pitop.supplier.entity.Supplier;
import com.pitop.supplier.service.SupplierSV;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.map.HashedMap;
import org.apache.ibatis.session.RowBounds;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service("materialSV")
@Slf4j
public class MaterialSVImpl extends BaseSVImpl<Material, Long> implements MaterialSV {

    @Autowired
    private MaterialDAO materialDAO;

    @Autowired
    private MaterialSupplierDAO materialSupplierDAO;

    @Autowired
    private SupplierDAO supplierDAO;

    @Autowired
    private MaterialUnitSV materialUnitSV;

    @Autowired
    private MaterialCurrencySV materialCurrencySV;

    @Autowired
    private SupplierSV supplierSV;

    @Autowired
    private MaterialLogDAO materialLogDAO;



    @Resource
    private UidGenerator uidGenerator;

    @Override
    protected BaseDAO getBaseDAO() {
        return materialDAO;
    }

    /**
     * 保存account对象
     *
     * @param entity 实体
     * @throws BaseException
     */
    @Override
    public void save(Material entity) throws BaseException {
        entity.setCode(String.valueOf(uidGenerator.getUID()));
        entity.setState(MaterialState.Enable.name());
        entity.setCreateTime(new Date());
        entity.setUpdateTime(new Date());
        super.save(entity);
    }

    /**
     * 新增
     *
     * @param material 供应材料实体
     * @param account
     *@param accountCode @return Material
     */
    @Override
    public Material insert(Material material, String account, String accountCode) {
        material.setCode(String.valueOf(uidGenerator.getUID()));
        material.setState(MaterialState.Enable.name());
        material.setCreateTime(new Date());
        material.setUpdateTime(new Date());
        super.save(material);

        //保存日志信息
        String summery = "管理员" + account +"添加了物料" + material.getName();
        MaterialLog materialLog = new MaterialLog(material.getCode(), MaterialLogState.Create.name(), accountCode, account, summery);
        materialLogDAO.insert(materialLog);
        return material;
    }

    @Override
    public List<MaterialVO> listByCategoryName(Material material, int offset, int limit) {
        if (offset < 0) {
            offset = 0;
        }

        if (limit < 0) {
            limit = Page.limit;
        }

        Map<String, Object> map;
        if (material != null) {
            map = JSON.parseObject(JSON.toJSONString(material, SerializerFeature.WriteDateUseDateFormat));
        } else {
            map = new HashMap<>();
        }
        List<Material> materials = materialDAO.listByCategoryName(map, new RowBounds(offset, limit));
        List<MaterialVO> materialVOS = StringTools.convertList(materials, MaterialVO.class);
        for (MaterialVO materialVO : materialVOS) {
            materialVO.setSuppliers(supplierDAO.loadListByMaterialCode(materialVO.getCode()));
        }
        return materialVOS;
    }

    @Override
    public int countByCategoryName(Material material) {
        Map<String, Object> map;
        if (material != null) {
            map = JSON.parseObject(JSON.toJSONString(material, SerializerFeature.WriteDateUseDateFormat));
        } else {
            map = new HashMap<>();
        }
        return materialDAO.countByCategoryName(map);
    }


    /**
     * 加载一个对象Material
     *
     * @param id * @param code 编码* @param suppierCode 供应商编码
     * @return Material
     */
    @Override
    public MaterialVO load(Long id, String code) {
        if (id == null && code == null) {
            throw new MaterialException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        Map<String, Object> param = new HashMap<>();
        param.put("id", id);
        param.put("code", code);
        Material material = materialDAO.load(param);
        MaterialVO materialVO = new MaterialVO();
        if (material != null) {
            materialVO = StringTools.convertObject(material, MaterialVO.class);
            List<Supplier> suppliers = supplierDAO.loadListByMaterialCode(material.getCode());
            Map<String, Object> params;
            MaterialSupplier materialSupplier;
            for (Supplier supplier : suppliers) {
                params = new HashedMap();
                params.put("suppierCode", supplier.getCode());
                params.put("materialCode", material.getCode());
                materialSupplier = materialSupplierDAO.load(params);
                supplier.setMaterialSupplier(materialSupplier);
            }
            materialVO.setSuppliers(suppliers);
        }
        return materialVO;
    }

    /**
     * 加载一个对象Material 通过id
     *
     * @param id
     * @return Material
     */
    @Override
    public MaterialVO loadById(Long id) {
        if (id == null) {
            throw new MaterialException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        Material material = materialDAO.loadById(id);
        MaterialVO materialVO = new MaterialVO();
        if (material != null) {
            materialVO = StringTools.convertObject(material, MaterialVO.class);
            List<Supplier> suppliers = supplierDAO.loadListByMaterialCode(material.getCode());
            Map<String, Object> params;
            MaterialSupplier materialSupplier;
            for (Supplier supplier : suppliers) {
                params = new HashedMap();
                params.put("suppierCode", supplier.getCode());
                params.put("materialCode", material.getCode());
                materialSupplier = materialSupplierDAO.load(params);
                supplier.setMaterialSupplier(materialSupplier);
            }
            materialVO.setSuppliers(suppliers);
        }
        return materialVO;
    }


    /**
     * 加载一个对象Material 通过code
     *
     * @param code 编码
     * @return Material
     */
    @Override
    public MaterialVO loadByCode(String code) {
        if (code == null) {
            throw new MaterialException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        Material material = materialDAO.loadByCode(code);
        MaterialVO materialVO = new MaterialVO();
        if (material != null) {
            materialVO = StringTools.convertObject(material, MaterialVO.class);
            List<Supplier> suppliers = supplierDAO.loadListByMaterialCode(material.getCode());
            Map<String, Object> params;
            MaterialSupplier materialSupplier;
            for (Supplier supplier : suppliers) {
                params = new HashedMap();
                params.put("suppierCode", supplier.getCode());
                params.put("materialCode", material.getCode());
                materialSupplier = materialSupplierDAO.load(params);
                supplier.setMaterialSupplier(materialSupplier);
            }
            materialVO.setSuppliers(suppliers);
        }
        return materialVO;
    }

    /**
     * 加载一个对象Material 通过名称
     *
     * @param name 名称
     * @return Material
     */
    @Override
    public Material loadByName(String name) {
        if (name == null) {
            throw new MaterialException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        Map<String, Object> params = new HashedMap();
        params.put("name", name);
        return materialDAO.load(params);
    }

    /**
     * 加载一个对象Material 通过suppierCode
     *
     * @param suppierCode 供应商编码
     * @return Material
     */
   /* @Override
    public Material loadBySuppierCode(String suppierCode) {
        if (suppierCode == null) {
            throw new MaterialException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        return materialDAO.loadBySuppierCode(suppierCode);
    }*/


    /**
     * 根据主键id,oldStates 共同更新 Material 的状态到newState状态
     *
     * @param id
     * @param newState  新状态
     * @param oldStates 旧状态集合
     */
    @Override
    public void updateStateById(Long id, MaterialState newState, MaterialState... oldStates) {
        if (id == null) {
            throw new MaterialException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        if (newState == null) {
            throw new MaterialException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        if (oldStates == null) {
            throw new MaterialException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        String[] states = new String[oldStates.length];
        for (int i = 0; i < oldStates.length; i++) {
            states[i] = oldStates[i].name();
        }
        materialDAO.updateStateById(id, new Date(), newState.name(), states);
    }

    /**
     * 根据主键code,oldStates 共同更新 Material 的状态到newState状态
     *
     * @param code      编码
     * @param newState  新状态
     * @param oldStates 旧状态集合
     */
    @Override
    public void updateStateByCode(String code, MaterialState newState, MaterialState... oldStates) {
        if (code == null) {
            throw new MaterialException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        if (newState == null) {
            throw new MaterialException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        if (oldStates == null) {
            throw new MaterialException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        String[] states = new String[oldStates.length];
        for (int i = 0; i < oldStates.length; i++) {
            states[i] = oldStates[i].name();
        }
        materialDAO.updateStateByCode(code, new Date(), newState.name(), states);
    }

    /**
     * 根据主键suppierCode,oldStates 共同更新 Material 的状态到newState状态
     *
     * @param suppierCode 供应商编码
     * @param newState    新状态
     * @param oldStates   旧状态集合
     */
    @Override
    public void updateStateBySuppierCode(String suppierCode, MaterialState newState, MaterialState... oldStates) {
        if (suppierCode == null) {
            throw new MaterialException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        if (newState == null) {
            throw new MaterialException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        if (oldStates == null) {
            throw new MaterialException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        String[] states = new String[oldStates.length];
        for (int i = 0; i < oldStates.length; i++) {
            states[i] = oldStates[i].name();
        }
        materialDAO.updateStateBySuppierCode(suppierCode, new Date(), newState.name(), states);
    }

    /**
     * 根据主键id 更新 Material 的状态到另一个状态
     *
     * @param id
     * @param state 状态
     */
    @Override
    public void updateById(Long id, MaterialState state) {
        if (id == null) {
            throw new MaterialException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        materialDAO.updateById(id, state.name(), new Date());
    }

    /**
     * 根据主键code 更新 Material 的状态到另一个状态
     *
     * @param code  编码
     * @param state 状态
     */
    @Override
    public void updateByCode(String code, MaterialState state) {
        if (code == null) {
            throw new MaterialException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        materialDAO.updateByCode(code, state.name(), new Date());
    }

    /**
     * 根据主键suppierCode 更新 Material 的状态到另一个状态
     *
     * @param suppierCode 供应商编码
     * @param state       状态
     */
    @Override
    public void updateBySuppierCode(String suppierCode, MaterialState state) {
        if (suppierCode == null) {
            throw new MaterialException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        materialDAO.updateBySuppierCode(suppierCode, state.name(), new Date());
    }


    /**
     * 删除对象Material
     *
     * @param id * @param code 编码* @param suppierCode 供应商编码
     * @return Material
     */
    @Override
    public void delete(Long id, String code, String suppierCode) {
        if (id == null && code == null && suppierCode == null) {
            throw new MaterialException(BaseException.BaseExceptionEnum.Illegal_Param);
        }
        Map<String, Object> param = new HashMap<>();
        param.put("id", id);
        param.put("code", code);
        param.put("suppierCode", suppierCode);
        materialDAO.delete(param);
    }


    /**
     * 查询Material分页
     *
     * @param material 对象
     * @param offset   查询开始行
     * @param limit    查询行数
     * @return List<Material>
     */
    @Override
    public List<MaterialVO> list(Material material, int offset, int limit) {
        if (offset < 0) {
            offset = 0;
        }

        if (limit < 0) {
            limit = Page.limit;
        }

        Map<String, Object> map;
        if (material != null) {
            map = JSON.parseObject(JSON.toJSONString(material, SerializerFeature.WriteDateUseDateFormat));
        } else {
            map = new HashMap<>();
        }
        List<Material> materials = materialDAO.list(map, new RowBounds(offset, limit));
        List<MaterialVO> materialVOS = StringTools.convertList(materials, MaterialVO.class);
        for (MaterialVO materialVO : materialVOS) {
            materialVO.setSuppliers(supplierDAO.loadListByMaterialCode(materialVO.getCode()));
        }
        return materialVOS;
    }

    @Override
    public List<MaterialVO> listForAssembly(String assemblyCode, String state, String name, int offset, int limit) {
        Map<String, Object> params = new HashedMap();
        params.put("assemblyCode", assemblyCode);
        params.put("state",  MaterialState.Enable.name());
        params.put("name", name);
        List<Material> materials = materialDAO.listForAssembly(params, new RowBounds(offset, limit));
        List<MaterialVO> materialVOS = StringTools.convertList(materials, MaterialVO.class);
        for (MaterialVO materialVO : materialVOS) {
            materialVO.setSuppliers(supplierDAO.loadListByMaterialCode(materialVO.getCode()));
        }
        return materialVOS;
    }

    @Override
    public List<MaterialVO> listForBom(String bomCode, String state, String name, int offset, int limit) {
        Map<String, Object> params = new HashedMap();
        params.put("bomCode", bomCode);
        params.put("state", MaterialState.Enable.name());
        params.put("name", name);
        params.put("type", BomDetailType.Material.name());
        List<Material> materials = materialDAO.listForBom(params, new RowBounds(offset, limit));
        List<MaterialVO> materialVOS = StringTools.convertList(materials, MaterialVO.class);
        for (MaterialVO materialVO : materialVOS) {
            materialVO.setSuppliers(supplierDAO.loadListByMaterialCode(materialVO.getCode()));
        }
        return materialVOS;
    }

    @Override
    public int countForAssembly(String assemblyCode, String state, String name) {
        Map<String, Object> params = new HashedMap();
        params.put("assemblyCode", assemblyCode);
        params.put("state",  MaterialState.Enable.name());
        params.put("name", name);
        return  materialDAO.countForAssembly(params);
    }

    @Override
    public int countForBom(String bomCode, String state, String name) {
        Map<String, Object> params = new HashedMap();
        params.put("bomCode", bomCode);
        params.put("state",  MaterialState.Enable.name());
        params.put("name", name);
        params.put("type", BomDetailType.Material.name());
        return  materialDAO.countForBom(params);
    }

    @Override
    public int count(Material material) {
        Map<String, Object> map;
        if (material != null) {
            map = JSON.parseObject(JSON.toJSONString(material, SerializerFeature.WriteDateUseDateFormat));
        } else {
            map = new HashMap<>();
        }
        return materialDAO.count(map);
    }

    /**
     * 查询Material分页
     *
     * @param id     * @param code  编码* @param suppierCode  供应商编码
     * @param offset 查询开始行
     * @param limit  查询行数
     * @return List<Material>
     */
    @Override
    public List<MaterialVO> list(Long id, String code, String suppierCode, int offset, int limit) {
        if (offset < 0) {
            offset = 0;
        }

        if (limit < 0) {
            limit = Page.limit;
        }
        Map<String, Object> param = new HashMap<>();
        param.put("id", id);
        param.put("code", code);
        param.put("suppierCode", suppierCode);
        List<Material> materials = materialDAO.list(param, new RowBounds(offset, limit));
        List<MaterialVO> materialVOS = StringTools.convertList(materials, MaterialVO.class);
        for (MaterialVO materialVO : materialVOS) {
            materialVO.setSuppliers(supplierDAO.loadListByMaterialCode(materialVO.getCode()));
        }
        return materialVOS;
    }

    @Override
    public int count(Long id, String code, String suppierCode) {
        Map<String, Object> param = new HashMap<>();
        param.put("id", id);
        param.put("code", code);
        param.put("suppierCode", suppierCode);
        return materialDAO.count(param);
    }

    @Override
    public BeanRet importMaterial(InputStream limitFileInputStream, String originalFilename) {
        //读取excel文件
        List<MaterialExcel> materialExcels = ExcelUtils.readExcel(limitFileInputStream, originalFilename, MaterialExcel.class);

        //生成单位sql
        StringBuffer unitSql = new StringBuffer();
        StringBuffer unitSqlFlag;
        MaterialUnit materialUnit;
        //生成币种sql
        StringBuffer currencySql = new StringBuffer();
        StringBuffer currencyFlag;
        MaterialCurrency materialCurrency;
        Map<String, Object> unitMap = new HashedMap();
        Map<String, Object> currencyMap = new HashedMap();
        for (MaterialExcel materialExcel : materialExcels) {
            //生成单位sql
            materialUnit = materialUnitSV.loadByUnit(materialExcel.getMaterialUnit());
            if (materialUnit == null) {
                unitSqlFlag = new StringBuffer();
                if (unitMap.get(materialExcel.getMaterialUnit()) == null) {
                    unitSqlFlag.append("INSERT INTO material_unit(code, unit) VALUES('");
                    unitSqlFlag.append(uidGenerator.getUID() + "','");
                    unitSqlFlag.append(materialExcel.getMaterialUnit() + "'");
                    unitSqlFlag.append(");").append("\r\n");
                    unitSql.append(unitSqlFlag);
                    unitMap.put(materialExcel.getMaterialUnit(), materialExcel);
                }
            }
            //生成币种sql
            materialCurrency = materialCurrencySV.loadByCurrency(materialExcel.getMaterialCurrency());
            if (materialCurrency == null) {
                currencyFlag = new StringBuffer();
                if (currencyMap.get(materialExcel.getMaterialCurrency()) == null) {
                    currencyFlag.append("INSERT INTO material_currency(code, currency) VALUES('");
                    currencyFlag.append(uidGenerator.getUID() + "','");
                    currencyFlag.append(materialExcel.getMaterialCurrency() + "'");
                    currencyFlag.append(");").append("\r\n");
                    currencySql.append(currencyFlag);
                    currencyMap.put(materialExcel.getMaterialCurrency(), materialExcel);
                }
            }
        }

        //生成材料sql和供应材料
        //生成材料供应商sql
        Supplier supplier1;
        Supplier supplier2;
        Supplier supplier3;
        StringBuffer materialSqlFlag;
        StringBuffer materialSql = new StringBuffer();
        StringBuffer supplierSqlFlag;
        StringBuffer materialSupplierSql = new StringBuffer();
        StringBuffer supplierNotExist = new StringBuffer();
        String code;
        for (MaterialExcel materialExcel : materialExcels) {
            code = uidGenerator.getUID() + "";
            supplier1 = supplierSV.loadByName(materialExcel.getTop1());
            if (supplier1 != null) {
                supplierSqlFlag = new StringBuffer();
                supplierSqlFlag.append("INSERT INTO  material_supplier(suppierCode, materialCode,level,state) VALUES('");
                supplierSqlFlag.append(supplier1.getCode()).append("','");
                supplierSqlFlag.append(code).append("','");
                supplierSqlFlag.append("1").append("','");
                supplierSqlFlag.append(MaterialSupplierState.Enable.name()).append("'");
                supplierSqlFlag.append(");").append("\r\n");
                materialSupplierSql.append(supplierSqlFlag);
            }
            supplier2 = supplierSV.loadByName(materialExcel.getTop2());
            if (supplier2 != null) {
                supplierSqlFlag = new StringBuffer();
                supplierSqlFlag.append("INSERT INTO  material_supplier(suppierCode, materialCode,level,state) VALUES('");
                supplierSqlFlag.append(supplier2.getCode()).append("','");
                supplierSqlFlag.append(code).append("','");
                supplierSqlFlag.append("2").append("','");
                supplierSqlFlag.append(MaterialSupplierState.Enable.name()).append("'");
                supplierSqlFlag.append(");").append("\r\n");
                materialSupplierSql.append(supplierSqlFlag);
            }
            supplier3 = supplierSV.loadByName(materialExcel.getTop3());
            if (supplier3 != null) {
                supplierSqlFlag = new StringBuffer();
                supplierSqlFlag.append("INSERT INTO  material_supplier(suppierCode, materialCode,level,state) VALUES('");
                supplierSqlFlag.append(supplier3.getCode()).append("','");
                supplierSqlFlag.append(code).append("','");
                supplierSqlFlag.append("3").append("','");
                supplierSqlFlag.append(MaterialSupplierState.Enable.name()).append("'");
                supplierSqlFlag.append(");").append("\r\n");
                materialSupplierSql.append(supplierSqlFlag);
            }
            if (supplier1 != null || supplier2 != null || supplier3 != null) {
                materialSqlFlag = new StringBuffer();
                materialSqlFlag.append("INSERT INTO material(code, name, num, state, factory_code, material_verion, star, fob, moq, cycle_time, materialUnit, materialCurrency) VALUES('");
                materialSqlFlag.append(code).append("','");
                materialSqlFlag.append(materialExcel.getName()).append("','");
                materialSqlFlag.append(materialExcel.getNum()).append("','");
                materialSqlFlag.append(MaterialState.Enable.name()).append("','");
                materialSqlFlag.append(materialExcel.getFactoryCode()).append("','");
                materialSqlFlag.append(materialExcel.getMaterialVerion()).append("','");
                materialSqlFlag.append("5").append("','");
                materialSqlFlag.append(materialExcel.getFob()).append("','");
                materialSqlFlag.append(materialExcel.getMoq()).append("','");
                materialSqlFlag.append(materialExcel.getCycleTime()).append("','");
                materialSqlFlag.append(materialExcel.getMaterialUnit()).append("','");
                materialSqlFlag.append(materialExcel.getMaterialCurrency()).append("'");
                materialSqlFlag.append(");").append("\r\n");
                materialSql.append(materialSqlFlag);
            }
        }

        try {
            File file = FileUtil.creatFile("C:\\material", "sql");
            FileOutputStream fos = new FileOutputStream(file);
            byte[] paymentSqlByte = unitSql.toString().getBytes();
            fos.write(paymentSqlByte);
            byte[] supplierSqlByte = currencySql.toString().getBytes();
            fos.write(supplierSqlByte);
            byte[] materialSqlByte = materialSql.toString().getBytes();
            fos.write(materialSqlByte);
            byte[] materialSupplierSqlByte = materialSupplierSql.toString().getBytes();
            fos.write(materialSupplierSqlByte);
            fos.flush();
            fos.close();

        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }


}
